package hibernatemock;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import lombok.Getter;
import lombok.Setter;

public class SmartClass {

	@Getter @Setter private Class<?> collectionType;
	@Getter @Setter private Class<?> beanType;

	public SmartClass(Class<?> clazz) {
		if (isCollection(clazz)) {
			collectionType = clazz;
		} else {
			beanType = clazz;
		}
	}

	public SmartClass(Field field) {
		field.setAccessible(true);
		Class<?> fieldType = field.getType();
		if (isCollection(fieldType)) {
			collectionType = fieldType;
			beanType = getCollectionGenericType(field);
		} else {
			beanType = fieldType;
		}
	}

	public boolean isCollection() {
		return collectionType != null;
	}

	public Class<?> getTrueType() {
		return collectionType != null ? collectionType : beanType;
	}

	private Class<?> getCollectionGenericType(Field field) {
		return (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
	}

	private boolean isCollection(Class<?> clazz) {
		return Collection.class.isAssignableFrom(clazz);
	}

	@Override public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((getTrueType() == null) ? 0 : getTrueType().hashCode());
		return result;
	}

	@Override public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SmartClass other = (SmartClass) obj;
		if (getTrueType() == null) {
			if (other.getTrueType() != null)
				return false;
		} else if (!getTrueType().equals(other.getTrueType()))
			return false;
		return true;
	}

}
